home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3.2 / Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO / packet / n17jsrc / cmdparse.c < prev    next >
C/C++ Source or Header  |  1991-08-22  |  7KB  |  383 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *        bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *        handle string escaped sequences
  11.  */
  12. #include <stdio.h>
  13. #include "global.h"
  14. #include "proc.h"
  15. #include "cmdparse.h"
  16.  
  17. struct boolcmd {
  18.     char *str;    /* Token */
  19.     int val;    /* Value */
  20. };
  21.  
  22. static struct boolcmd Boolcmds[] = {
  23.     "y",        1,    /* Synonyms for "true" */
  24.     "yes",        1,
  25.     "true",        1,
  26.     "on",        1,
  27.     "1",        1,
  28.     "set",        1,
  29.     "enable",    1,
  30.  
  31.     "n",        0,    /* Synonyms for "false" */
  32.     "no",        0,
  33.     "false",    0,
  34.     "off",        0,
  35.     "0",        0,
  36.     "clear",    0,
  37.     "disable",    0,
  38.     NULLCHAR
  39. };
  40.  
  41. static char *stringparse __ARGS((char *line));
  42.  
  43. static char *
  44. stringparse(line)
  45. char *line;
  46. {
  47.     register char *cp = line;
  48.     unsigned long num;
  49.  
  50.     while ( *line != '\0' && *line != '\"' ) {
  51.         if ( *line == '\\' ) {
  52.             line++;
  53.             switch ( *line++ ) {
  54.             case 'n':
  55.                 *cp++ = '\n';
  56.                 break;
  57.             case 't':
  58.                 *cp++ = '\t';
  59.                 break;
  60.             case 'v':
  61.                 *cp++ = '\v';
  62.                 break;
  63.             case 'b':
  64.                 *cp++ = '\b';
  65.                 break;
  66.             case 'r':
  67.                 *cp++ = '\r';
  68.                 break;
  69.             case 'f':
  70.                 *cp++ = '\f';
  71.                 break;
  72.             case 'a':
  73.                 *cp++ = '\a';
  74.                 break;
  75.             case '\\':
  76.                 *cp++ = '\\';
  77.                 break;
  78.             case '\?':
  79.                 *cp++ = '\?';
  80.                 break;
  81.             case '\'':
  82.                 *cp++ = '\'';
  83.                 break;
  84.             case '\"':
  85.                 *cp++ = '\"';
  86.                 break;
  87.             case 'x':
  88.                 num = strtoul( --line, &line, 16 );
  89.                 *cp++ = (char) num;
  90.                 break;
  91.             case '0':
  92.             case '1':
  93.             case '2':
  94.             case '3':
  95.             case '4':
  96.             case '5':
  97.             case '6':
  98.             case '7':
  99.                 num = strtoul( --line, &line, 8 );
  100.                 *cp++ = (char) num;
  101.                 break;
  102.             case '\0':
  103.                 return NULLCHAR;
  104.             default:
  105.                 *cp++ = *(line - 1);
  106.                 break;
  107.             };
  108.         } else {
  109.             *cp++ = *line++;
  110.         }
  111.     }
  112.  
  113.     if ( *line == '\"' )
  114.         line++;     /* skip final quote */
  115.     *cp = '\0';        /* terminate string */
  116.     return line;
  117. }
  118.  
  119. int
  120. cmdparse(cmds,line,p)
  121. struct cmds cmds[];
  122. register char *line;
  123. void *p;
  124. {
  125.     struct cmds *cmdp;
  126.     char *argv[NARG],*cp;
  127.     char **pargv;
  128.     int argc,i;
  129.  
  130.     /* Remove cr/lf */
  131.     rip(line);
  132.  
  133.     for(argc = 0;argc < NARG;argc++)
  134.         argv[argc] = NULLCHAR;
  135.  
  136.     for(argc = 0;argc < NARG;){
  137.         register int qflag = FALSE;
  138.  
  139.         /* Skip leading white space */
  140.         while(*line == ' ' || *line == '\t')
  141.             line++;
  142.         if(*line == '\0')
  143.             break;
  144.         /* return if comment character first non-white */
  145.         if ( argc == 0  &&  *line == '#' )
  146.             return 0;
  147.         /* Check for quoted token */
  148.         if(*line == '"'){
  149.             line++;    /* Suppress quote */
  150.             qflag = TRUE;
  151.         }
  152.         argv[argc++] = line;    /* Beginning of token */
  153.  
  154.         if(qflag){
  155.             /* Find terminating delimiter */
  156.             if((line = stringparse(line)) == NULLCHAR){
  157.                 return -1;
  158.             }
  159.         } else {
  160.             /* Find space or tab. If not present,
  161.              * then we've already found the last
  162.              * token.
  163.              */
  164.             if((cp = strchr(line,' ')) == NULLCHAR
  165.              && (cp = strchr(line,'\t')) == NULLCHAR){
  166.                 break;
  167.             }
  168.             *cp++ = '\0';
  169.             line = cp;
  170.         }
  171.     }
  172.     if (argc < 1) {        /* empty command line */
  173.         argc = 1;
  174.         argv[0] = "";
  175.     }
  176.     /* Look up command in table; prefix matches are OK */
  177.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  178.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  179.             break;
  180.     }
  181.     if(cmdp->name == NULLCHAR) {
  182.         if(cmdp->argc_errmsg != NULLCHAR)
  183.             tprintf("%s\n",cmdp->argc_errmsg);
  184.         return -1;
  185.     } else {
  186.         if(argc < cmdp->argcmin) {
  187.             /* Insufficient arguments */
  188.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  189.             return -1;
  190.         } else {
  191.             if(cmdp->stksize == 0){
  192.                 return (*cmdp->func)(argc,argv,p);
  193.             } else {
  194.                 /* Make private copy of argv and args,
  195.                  * spawn off subprocess and return.
  196.                  */
  197.                 pargv = (char **)callocw(argc,sizeof(char *));
  198.                 for(i=0;i<argc;i++)
  199.                     pargv[i] = strdup(argv[i]);
  200.                 newproc(cmdp->name,cmdp->stksize,
  201.                 (void (*)())cmdp->func,argc,pargv,p,1);
  202.                 return(0);
  203.             }
  204.         }
  205.     }
  206. }
  207.  
  208. /* Call a subcommand based on the first token in an already-parsed line */
  209. int
  210. subcmd(tab,argc,argv,p)
  211. struct cmds tab[];
  212. int argc;
  213. char *argv[];
  214. void *p;
  215. {
  216.     register struct cmds *cmdp;
  217.     char **pargv;
  218.     int found = 0;
  219.     int i;
  220.  
  221.     /* Strip off first token and pass rest of line to subcommand */
  222.     if (argc < 2) {
  223.         if (argc < 1)
  224.             tprintf("SUBCMD - Don't know what to do?\n");
  225.         else
  226.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  227.         return -1;
  228.     }
  229.     argc--;
  230.     argv++;
  231.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  232.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  233.             found = 1;
  234.             break;
  235.         }
  236.     }
  237.     if(!found){
  238.         tprintf("valid subcommands:");
  239.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  240.             if(tprintf(" %s",cmdp->name) == EOF)
  241.                 return -1;
  242.         tprintf("\n");
  243.         return -1;
  244.     }
  245.     if(argc < cmdp->argcmin){
  246.         if(cmdp->argc_errmsg != NULLCHAR)
  247.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  248.         return -1;
  249.     }
  250.     if(cmdp->stksize == 0){
  251.         return (*cmdp->func)(argc,argv,p);
  252.     } else {
  253.         /* Make private copy of argv and args */
  254.         pargv = (char **)callocw(argc,sizeof(char *));
  255.         for(i=0;i<argc;i++)
  256.             pargv[i] = strdup(argv[i]);
  257.         newproc(cmdp->name,cmdp->stksize,
  258.          (void (*)())cmdp->func,argc,pargv,p,1);
  259.         return(0);
  260.     }
  261. }
  262.  
  263. /* Subroutine for setting and displaying boolean flags */
  264. int
  265. setbool(var,label,argc,argv)
  266. int *var;
  267. char *label;
  268. int argc;
  269. char *argv[];
  270. {
  271.     struct boolcmd *bc;
  272.  
  273.     if(argc < 2){
  274.         tprintf("%s: %s\n",label,*var ? "on":"off");
  275.         return 1;
  276.     }
  277.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  278.         if(strcmpi(argv[1],bc->str) == 0){
  279.             *var = bc->val;
  280.             return 0;
  281.         }
  282.     }
  283.     tprintf("Valid options:");
  284.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  285.         if(tprintf(" %s",bc->str) == EOF)
  286.             return 1;
  287.     tprintf("\n");
  288.     return 1;
  289. }
  290.  
  291.  
  292. /* Subroutine for setting and displaying bit values */
  293. int
  294. bit16cmd(bits,mask,label,argc,argv)
  295. int16 *bits;
  296. int16 mask;
  297. char *label;
  298. int argc;
  299. char *argv[];
  300. {
  301.     int doing = (*bits & mask);
  302.     int result = setbool( &doing, label, argc, argv );
  303.  
  304.     if ( !result ) {
  305.         if ( doing )
  306.             *bits |= mask;
  307.         else
  308.             *bits &= ~mask;
  309.     }
  310.     return result;
  311. }
  312.  
  313.  
  314. /* Subroutine for setting and displaying long variables */
  315. int
  316. setlong(var,label,argc,argv)
  317. long *var;
  318. char *label;
  319. int argc;
  320. char *argv[];
  321. {
  322.     if(argc < 2){
  323.         tprintf("%s: %ld\n",label,*var);
  324.         return 1;
  325.     } else {
  326.         *var = atol(argv[1]);
  327.         return 0;
  328.     }
  329.  
  330. }
  331. /* Subroutine for setting and displaying short variables */
  332. int
  333. setshort(var,label,argc,argv)
  334. unsigned short *var;
  335. char *label;
  336. int argc;
  337. char *argv[];
  338. {
  339.     if(argc < 2){
  340.         tprintf("%s: %u\n",label,*var);
  341.         return 1;
  342.     } else {
  343.         *var = atoi(argv[1]);
  344.         return 0;
  345.     }
  346. }
  347. /* Subroutine for setting and displaying integer variables */
  348. int
  349. setint(var,label,argc,argv)
  350. int *var;
  351. char *label;
  352. int argc;
  353. char *argv[];
  354. {
  355.     if(argc < 2){
  356.         tprintf("%s: %i\n",label,*var);
  357.         return 1;
  358.     } else {
  359.         *var = atoi(argv[1]);
  360.         return 0;
  361.     }
  362.  
  363. }
  364.  
  365. /* Subroutine for setting and displaying unsigned integer variables */
  366. int
  367. setuns(var,label,argc,argv)
  368. unsigned *var;
  369. char *label;
  370. int argc;
  371. char *argv[];
  372. {
  373.     if(argc < 2){
  374.         tprintf("%s: %u\n",label,*var);
  375.         return 1;
  376.     } else {
  377.         *var = atoi(argv[1]);
  378.         return 0;
  379.     }
  380. }
  381.  
  382.  
  383.